﻿using NetFrame;
using NetFrame.EnDecode;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Net.Sockets;
using System.Text;

namespace NetIOFrame {
    public class NetIO {
        private static NetIO instance;

        public static NetIO Instance {
            get {
                if (instance == null) {
                    instance = new NetIO();
                }
                return instance;
            }
        }
        
        Socket socket;

        /// <summary>
        /// socket接收数据时用到的缓冲区
        /// </summary>
        byte[] readBuffer = new byte[1042];

        //处理数据的缓冲区
        List<byte> cache = new List<byte>();

        //发送数据的消息队列
        //public Queue<byte[]> write_queue = new Queue<byte[]>();
        public Queue<TransModel> write_queue = new Queue<TransModel>();

        bool isWrite, isRead;

        public static string connectstring = "127.0.0.1";

        BaseCode code=new BaseCode();

        private NetIO() {
            try {

                socket = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);

                socket.Connect(connectstring, 6666);

                socket.BeginReceive(readBuffer, 0, 1024, SocketFlags.None, ReceiveCallBack, null);
            }
            catch (Exception ex) {
                Console.WriteLine("无法连接服务器，请重启客户端或联系服务器管理员");
            }
        }

        void ReceiveCallBack(IAsyncResult result) {
            int length = socket.EndReceive(result);
            byte[] data = new byte[length];
            Buffer.BlockCopy(readBuffer, 0, data, 0, length);

            cache.AddRange(data);

            if (!isRead) {
                isRead = true;
                Read();
            }

            socket.BeginReceive(readBuffer, 0, 1024, SocketFlags.None, ReceiveCallBack, null);
        }

        /// <summary>
        /// 对缓冲区数据进行处理
        /// </summary>
        void Read() {

            //byte[] result=cache.ToArray();
            //cache.Clear();

            //string con = Encoding.UTF8.GetString(result);

            //Console.WriteLine(con);

            //isRead = false;
            TransModel model = code.Decoding(ref cache);
            if (model == null) {
                isRead = false;
                return;
            }

            //todo 处理 model
            //example
            Console.Write(model.getMessage<string>());

            Read();
        }

        public void Send(TransModel model) {
            //对传输数据模型编码 socketmodel
            //byte[] result = Encoding.UTF8.GetBytes(content);
            write_queue.Enqueue(model);

            if (!isWrite) {
                isWrite = true;
                Write();
            }
        }

        public void Write() {
            if (write_queue.Count == 0) {
                isWrite = false;
                return;
            }

            //消息队列不为空，取出来并发送
            TransModel m = write_queue.Dequeue();

            byte[] queue = code.Encoding(m);

            if (queue == null) {
                isWrite = false;
                return;
            }

            try {
                socket.BeginSend(queue, 0, queue.Length, SocketFlags.None, SendCallBack, null);
            }
            catch (Exception ex) {
            }

        }

        /// <summary>
        /// 发送数据
        /// </summary>
        /// <param name="result"></param>
        void SendCallBack(IAsyncResult result) {
            socket.EndSend(result);
            Write();
        }
    }
}
